<?php
/**
 * 操纵文件类
 * 例子：
 * Files::createDir('a/1/2/3');                    测试建立文件夹 建一个a/1/2/3文件夹
 * Files::createFile('b/1/2/3');                    测试建立文件        在b/1/2/文件夹下面建一个3文件
 * Files::createFile('b/1/2/3.exe');             测试建立文件        在b/1/2/文件夹下面建一个3.exe文件
 * Files::copyDir('b','d/e');                    测试复制文件夹 建立一个d/e文件夹，把b文件夹下的内容复制进去
 * Files::copyFile('b/1/2/3.exe','b/b/3.exe'); 测试复制文件        建立一个b/b文件夹，并把b/1/2文件夹中的3.exe文件复制进去
 * Files::moveDir('a/','b/c');                    测试移动文件夹 建立一个b/c文件夹,并把a文件夹下的内容移动进去，并删除a文件夹
 * Files::moveFile('b/1/2/3.exe','b/d/3.exe'); 测试移动文件        建立一个b/d文件夹，并把b/1/2中的3.exe移动进去
 * Files::unlinkFile('b/d/3.exe');             测试删除文件        删除b/d/3.exe文件
 * Files::unlinkDir('d');                      测试删除文件夹 删除d文件夹
 */

namespace helper;

class Files
{


  /**
   * 建立文件夹
   * @param $dir
   * @return bool|void
   */
  static public function createDir($dir)
  {
    return is_dir($dir) or (self::createDir(dirname($dir)) and mkdir($dir, 0755));
  }

  /**
   * 建立文件
   * @param string $aimUrl
   * @param boolean $overWrite 该参数控制是否覆盖原文件
   * @return boolean
   */
  static public function createFile($aimUrl, $overWrite = false)
  {
    if (file_exists($aimUrl) && $overWrite == false) {
      return false;
    } elseif (file_exists($aimUrl) && $overWrite == true) {
      self::unlinkFile($aimUrl);
    }
    $aimDir = dirname($aimUrl);
    self::createDir($aimDir);
    touch($aimUrl);
    return true;
  }

  /**
   * 写文件
   * @param $filename
   * @param $writeText
   * @param string $mod
   * @return bool
   */
  static public function writeFile($filename, $writeText, $mod = 'w')
  {
    if (!file_exists($filename)) self::createFile($filename); //没有文件先创建
    if (@$fp = fopen($filename, $mod)) {
      flock($fp, 2);
      fwrite($fp, $writeText);
      fclose($fp);
      return true;
    } else {
      return false;
    }
  }

  /**
   * 文件重命名
   * @param $oldname
   * @param $newname
   * @return bool
   */
  static public function rename($oldname, $newname)
  {
    if (($newname != $oldname) && is_writable($oldname)) return rename($oldname, $newname);
    return false;
  }

  /**
   * 移动文件夹
   * @param string $oldDir
   * @param string $aimDir
   * @return boolean
   */
  static public function moveDir($oldDir, $aimDir)
  {
    if (self::copyDir($oldDir, $aimDir)) return self::unlinkDir($oldDir);
    return false;
  }

  /**
   * 移动文件
   * @param string $fileUrl
   * @param string $aimUrl
   * @param boolean $overWrite 该参数控制是否覆盖原文件
   * @return boolean
   */
  static public function moveFile($fileUrl, $aimUrl, $overWrite = false)
  {
    is_dir($aimUrl) or mkdir($aimUrl, 0755, true);
    if (is_file($fileUrl) && is_dir($aimUrl)) {
      copy($fileUrl, $aimUrl . '/' . basename($fileUrl));
      return unlink($fileUrl);
    }
    return false;
  }

  /**
   * 删除文件夹
   * @param string $dir
   * @return boolean
   */
  static public function unlinkDir($dir)
  {
    $dir = self::pathReplace($dir);
    if (!is_dir($dir)) return true;
    foreach (glob($dir . "/*") as $v) {
      is_dir($v) ? self::unlinkDir($v) : unlink($v);
    }
    return rmdir($dir);
  }

  /**
   * 删除文件
   * @param string $aimUrl
   * @return boolean
   */
  static public function unlinkFile($aimUrl)
  {
    if (is_file($aimUrl)) {
      return unlink($aimUrl);
    }
    return true;
  }

  /**
   * 复制文件夹
   * @param string $oldDir
   * @param string $aimDir
   * @return boolean
   */
  static public function copyDir($oldDir, $aimDir)
  {
    $oldDir = rtrim($oldDir, '/') . '/';
    $aimDir = rtrim($aimDir, '/') . '/';
    is_dir($aimDir) or mkdir($aimDir, 0755, true);
    foreach (glob($oldDir . '/*') as $v) {
      $to = $aimDir . '/' . basename($v);
      is_file($v) ? copy($v, $to) : self::copyDir($v, $to);
    }
    return true;
  }

  /**
   * 复制文件
   * @param string $fileUrl
   * @param string $aimUrl
   * @return boolean
   */
  static public function copyFile($fileUrl, $aimUrl)
  {
    if (!is_file($fileUrl)) {
      return false;
    }
    self::createDir(dirname($aimUrl));
    return copy($fileUrl, $aimUrl);
  }

  /**
   * 遍历目录文件
   * @param $dir
   * @param array $ext
   * @return array
   */
  static public function getDir($dir, $ext = [])
  {
    $list = [];
    if (empty($dir)) {
      return $list;
    }
    foreach (glob($dir . '/*') as $id => $v) {
      $info    = pathinfo($v);
      $listDir = 0;
      if (empty($ext)) {
        $listDir = 1;
      } else {
        if (in_array($info['extension'], $ext)) {
          $listDir = 1;
        }
      }
      if ($listDir == 1) {
        $list [$id] ['path']       = $v;
        $list [$id] ['type']       = filetype($v);
        $list [$id] ['dirname']    = $info['dirname'];
        $list [$id] ['basename']   = $info['basename'];
        $list [$id] ['filename']   = $info['filename'];
        $list [$id] ['extension']  = isset($info['extension']) ? $info['extension'] : '';
        $list [$id] ['file_mtime'] = filemtime($v);
        $list [$id] ['file_atime'] = fileatime($v);
        $list [$id] ['size']       = is_file($v) ? filesize($v) : self::size($v);
        $list [$id] ['is_write']   = is_writeable($v);
        $list [$id] ['is_read']    = is_readable($v);
      }
    }
    return array_values($list);
  }

  /**
   * 遍历树型文件目录
   * @param $dir
   * @return array
   */
  static public function tree($dir)
  {
    $files = [];
    $i     = 0;
    if (@$handle = opendir($dir)) { //注意这里要加一个@，不然会有warning错误提示：）
      while (($file = readdir($handle)) !== false) {
        if ($file != ".." && $file != ".") { //排除根目录；
          if (is_dir($dir . "/" . $file)) { //如果是子文件夹，就进行递归
            $files[$i]['name']     = $file;
            $files[$i]['open']     = false;
            $files[$i]["children"] = self::tree($dir . "/" . $file);
          } else { //不然就将文件的名字存入数组；
            $files[$i] = ['name' => $file];
          }
          $i += 1;
        }
      }
      //children
      closedir($handle);
      return $files;
    }
    return [];
  }

  /**
   * 获取目录大小
   * @param $dir
   * @return false|int
   */
  static public function size($dir)
  {
    $s = 0;
    foreach (glob($dir . '/*') as $v) {
      $s += is_file($v) ? filesize($v) : self::size($v);
    }
    return $s;
  }

  /**
   * 获取文件后缀名
   * @param $file
   * @return mixed
   */
  static public function getExt($file)
  {
    $file = self::pathReplace($file);
    return pathinfo($file, PATHINFO_EXTENSION);
  }

  /**
   * 路径替换
   * @param $path
   * @return mixed
   */
  static public function pathReplace($path)
  {
    return str_replace('//', '/', str_replace('\\', '/', $path));
  }

  /**
   * 字节格式化 把字节数格式为 B K M G T P E Z Y 描述的大小
   * @param int $size 大小
   * @param int $dec 显示类型
   * @return int
   */
  static public function byteFormat($size, $dec = 2)
  {
    $unit = array("B", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB");
    $pos  = 0;
    while ($size >= 1024) {
      $size /= 1024;
      $pos++;
    }
    return round($size, $dec) . " " . $unit[$pos];
  }
}